const Consul = require('consul');
const AServiceRegistry = require('./AServiceRegistry');
const LoadBalancer = require('./loadbalancer/LoadBalancer');


/**
 * 使用 consul 作为微服务注册，发现和配置管理中心
 */
class ConsulServiceRegistry extends AServiceRegistry {

    client;
    watchor;
    loadBalancer;

    constructor(param) {
        super(param);

        this.loadBalancer = new LoadBalancer(param.SELECT_STRATEGY);

        console.debug("创建 consul 客户端", param.nodes);

        let [host, port] = param.nodes.split(":");

        this.client = new Consul({ //初始化注册对象
            host: host, //consul注册中心的地址，这里我用的本机地址
            port: port, //consul client服务的端口号
            promisify: true,
        });

        this.watchor = this.client.watch({
            method: this.client.health.state,
            options: {
                state: "passing"
            },
            backoffFactor: 1000,
        });

        console.info("consul 客户端连接成功");

    }

    /**
     * 监控注册的服务变更事件,如服务实例加入，移除，配置数据变更
     * @param {Array<String>} services 监控的服务集合
     */
    subscribeEvent(services) {
        this.watchor //
            .on("change", data => {
                console.log("consul change data:", data);

                services.forEach(service => {
                    let arr = data.filter(i => i.ServiceName == service).map(i => {
                        let healthUrl = i.Output.match(/HTTP\sGET\s(\S*):/)[1];
                        console.debug(`${service} health url is ${healthUrl}`)

                        return healthUrl.substring(0, healthUrl.indexOf("/", healthUrl.lastIndexOf(":")));
                    });

                    this.loadBalancer.updateCache(service, arr);
                });
            }) //
            .on("error", err => {
                console.error("error:", err);
            });
    }

    /**
     * 根据服务名称获取可访问的一个节点，如果有多个可用节点
     * @param {String} service 服务名称
     * @returns String 服务调用地址
     */
    getServiceNode(service) {
        return this.loadBalancer.getRealPath(service);
    }

    /**
     * 释放客户端
     */
    close() {
        console.debug("进入 close ");
        this.watchor.end();
    }
}

module.exports = ConsulServiceRegistry;